package com.estate.system.listener;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellExtra;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.estate.common.core.domain.req.TransactionDataReq;
import com.estate.common.enums.ResponseCodeEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 故障库导入
 * Excel模板的读取监听类
 *
 * @author yang
 */
@Data
@Slf4j
public class SalesDataExcelListener<T> extends BaseImportListener<T> {

    /**
     * 数据校验缓存
     */
    public List<String> CHECKLIST = new ArrayList<>();

    /**
     * 数据缓存
     */
    private List<String> DATALIST = new ArrayList<>();

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value
     * @param context context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        if (data instanceof TransactionDataReq) {
            TransactionDataReq d = (TransactionDataReq) data;
            // 导入参数校验
            if (ObjectUtils.isEmpty(d.getClientFirstName())) {
                CHECKLIST.add(
                        "【行：" + (
                                context.readRowHolder().getRowIndex() + 1) + " 列：" + 2 + " 值：" + "】"
                                + ResponseCodeEnum.EXCEL_IMPORT_PARAMS_EMPTY.getMessage());
                return;
            }
            if (ObjectUtils.isEmpty(d.getClientLastName())) {
                CHECKLIST.add(
                        "【行：" + (
                                context.readRowHolder().getRowIndex() + 1) + " 列：" + 3 + " 值：" + "】"
                                + ResponseCodeEnum.EXCEL_IMPORT_PARAMS_EMPTY.getMessage());
                return;
            }
            if (ObjectUtils.isEmpty(d.getListingStatus())) {
                CHECKLIST.add(
                        "【行：" + (
                                context.readRowHolder().getRowIndex() + 1) + " 列：" + 7 + " 值：" + "】"
                                + ResponseCodeEnum.EXCEL_IMPORT_PARAMS_EMPTY.getMessage());
                return;
            }
            if (ObjectUtils.isEmpty(d.getListingType())) {
                CHECKLIST.add(
                        "【行：" + (
                                context.readRowHolder().getRowIndex() + 1) + " 列：" + 9 + " 值：" + "】"
                                + ResponseCodeEnum.EXCEL_IMPORT_PARAMS_EMPTY.getMessage());
                return;
            }
            if (ObjectUtils.isEmpty(d.getListingTransactionDate())) {
                CHECKLIST.add(
                        "【行：" + (
                                context.readRowHolder().getRowIndex() + 1) + " 列：" + 17 + " 值：" + "】"
                                + ResponseCodeEnum.EXCEL_IMPORT_PARAMS_EMPTY.getMessage());
                return;
            }

        }
        super.getList().add(data);
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
// 获取当前行索引
        Integer rowIndex = context.readRowHolder().getRowIndex();

        if (exception instanceof IOException) {
            CHECKLIST.add(ResponseCodeEnum.EXCEL_FILE_READ_EXCEPTION.getMessage());
        }
        else if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException ex = (ExcelDataConvertException) exception;
            String errorMsg = handleDataConvertException(ex);
            CHECKLIST.add(errorMsg);
        }
        else if (exception instanceof NumberFormatException) {
            // 专门处理数字格式异常
            NumberFormatException nfe = (NumberFormatException) exception;
            String errorMsg = handleNumberFormatException(nfe, rowIndex, context);
            CHECKLIST.add(errorMsg);
        }
        else {
            // 其他异常
            CHECKLIST.add("第 " + (rowIndex + 1) + " 行数据解析异常: " + exception.getMessage());
        }
    }

    private String getColumnName(int columnIndex) {
        String[] columnNames = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
                "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z"};

        if (columnIndex < columnNames.length) {
            return columnNames[columnIndex];
        } else {
            // 处理超过Z的列名（AA, AB, ...）
            int firstChar = columnIndex / 26 - 1;
            int secondChar = columnIndex % 26;
            if (firstChar >= 0 && firstChar < columnNames.length) {
                return columnNames[firstChar] + columnNames[secondChar];
            }
        }
        return "列" + (columnIndex + 1);
    }

    private String handleDataConvertException(ExcelDataConvertException ex) {
        String cellData = String.valueOf(ex.getCellData());
        String columnName = getColumnName(ex.getColumnIndex());

        StringBuilder errorMsg = new StringBuilder();
        errorMsg.append("【行：").append(ex.getRowIndex() + 1)
                .append(" 列：").append(columnName)
                .append("(").append(ex.getColumnIndex() + 1).append(")")
                .append(" 值：").append(cellData).append("】");

        // 根据异常原因提供更具体的错误信息
        Throwable cause = ex.getCause();
        if (cause instanceof NumberFormatException) {
            errorMsg.append("数字格式不正确，包含非法字符");

            // 检查是否包含字母Z等非法字符
            if (cellData.matches(".*[A-Za-z].*")) {
                errorMsg.append("（包含字母：").append(cellData.replaceAll("[^A-Za-z]", "")).append("）");
            }
        } else {
            errorMsg.append("数据类型不匹配");
        }

        return errorMsg.toString();
    }

    private String handleNumberFormatException(NumberFormatException e, Integer rowIndex, AnalysisContext context) {
        try {
            // 获取当前行的数据
            Object currentRow = context.readRowHolder().getCurrentRowAnalysisResult();

            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append("【行：").append(rowIndex + 1).append("】");
            errorMsg.append("数字格式错误：").append(e.getMessage());

            // 如果能够获取到当前行数据，可以添加更多上下文信息
            if (currentRow != null) {
                errorMsg.append("，行数据：").append(currentRow.toString());
            }

            return errorMsg.toString();

        } catch (Exception ex) {
            return "【行：" + (rowIndex + 1) + "】数字格式解析失败";
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成！");
    }

    /**
     * 返回解析出来的List
     */
    public List<T> getData() {
        return super.getList();
    }

    /**
     * 读取额外信息：合并单元格
     */
    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        switch (extra.getType()) {
            case MERGE: {
                if (extra.getRowIndex() >= getHeadRowNumber()) {
                    super.getExtraMergeInfoList().add(extra);
                }
                break;
            }
            default:
        }
    }

    /**
     * 返回解析出来的合并单元格List
     */
    public List<CellExtra> getExtraMergeInfoList() {
        return super.getExtraMergeInfoList();
    }

    /**
     * 在这里进行模板的判断
     *
     * @param headMap 存放着导入表格的表头，键是索引，值是名称
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        // 获取数据实体的字段列表
        Field[] fields = TransactionDataReq.class.getDeclaredFields();
        // 获取当前字段上的ExcelProperty注解信息
        ExcelProperty fieldAnnotation = fields[0].getAnnotation(ExcelProperty.class);
        // 判断当前字段上是否存在ExcelProperty注解
        if (fieldAnnotation != null) {
            // 存在ExcelProperty注解则根据注解的index索引到表头中获取对应的表头名
            String headName = headMap.get(fieldAnnotation.index());
            // 判断表头是否为空或是否和当前字段设置的表头名不相同
        }

    }
}
